/*
 * Created by: Mark Lavrynenko
 * Email:	MarkLavrinenko@gmail.com
 * Project:	  Huffman
*/

#include "FileDataTarget.h"
#include <assert.h>

FileDataTarget::FileDataTarget(char const* fileName) : haveBits(0), byte(0)
{
	f = fopen(fileName, "wb");
	assert(NULL != f);
}


FileDataTarget::~FileDataTarget(void)
{
	finishByte();
	fclose(f);
}

bool FileDataTarget::putNextByte(uint8_t next)
{
	fputc(next, f);
	return !ferror(f);
}

bool FileDataTarget::putNextInt16(int16_t next)
{
	bool ans = true;
	ans &= putNextByte((next & 0xFF00) >> 8);
	ans &= putNextByte(next & 0x00FF);
	return ans;
}

bool FileDataTarget::putNextInt32(int32_t next)
{
	bool ans = true;
	ans &= putNextByte((next & 0xFF000000) >> 24);
	ans &= putNextByte((next & 0x00FF0000) >> 16);
	ans &= putNextByte((next & 0x0000FF00) >> 8);
	ans &= putNextByte(next & 0x000000FF);
	return ans;
}

bool FileDataTarget::putNextBit(const bool &value)
{
	if (value)
		byte |= 1 << (7 - haveBits);
	++haveBits;
	bool res = true;
	if (8 == haveBits)
	{
		haveBits = 0;
		res = putNextByte(byte);
		byte = 0;
	}
	return res;
}

bool FileDataTarget::putBitSequence(const vector<char> &bits)
{
	bool res = true;
	const size_t n = bits.size();
	//for (vector<bool>::const_iterator it = bits.begin(); it != bits.end() && res; ++it)
	for (size_t i = 0; i < n; ++i)
	{
		res &= putNextBit('1' == bits.at(i));
	}	
	return res;
}

void FileDataTarget::finishByte()
{
	if (haveBits)
	{
		putNextByte(byte);
		haveBits = 0;
		byte = 0;
	}
}